"""
增强版Kubernetes资源比较器
"""
from typing import Dict, List, Any, Optional, Tuple
from dataclasses import dataclass
import json
import yaml
from deepdiff import DeepDiff
import networkx as nx
import matplotlib.pyplot as plt

@dataclass
class ComparisonResult:
    """比较结果"""
    differences: Dict[str, Any]
    summary: Dict[str, Any]
    visualization: Optional[str] = None

class EnhancedResourceComparer:
    """增强版资源比较器"""
    
    def __init__(self):
        self._diff_graph = nx.DiGraph()
        
    def compare_resources(self, resource1: Dict[str, Any], resource2: Dict[str, Any],
                         ignore_paths: Optional[List[str]] = None) -> ComparisonResult:
        """
        比较两个资源
        
        Args:
            resource1: 第一个资源
            resource2: 第二个资源
            ignore_paths: 要忽略的路径列表
            
        Returns:
            ComparisonResult: 比较结果
        """
        # 1. 执行深度比较
        diff = DeepDiff(resource1, resource2, 
                       ignore_order=True,
                       report_repetition=True,
                       verbose_level=2,
                       exclude_paths=ignore_paths)
        
        # 2. 生成差异摘要
        summary = self._generate_diff_summary(diff)
        
        # 3. 生成可视化
        visualization = self._generate_visualization(resource1, resource2, diff)
        
        return ComparisonResult(
            differences=diff,
            summary=summary,
            visualization=visualization
        )
    
    def compare_resource_versions(self, resource: Dict[str, Any], 
                                version1: str, version2: str) -> ComparisonResult:
        """
        比较资源在不同版本间的差异
        
        Args:
            resource: 要比较的资源
            version1: 第一个版本
            version2: 第二个版本
            
        Returns:
            ComparisonResult: 比较结果
        """
        # 1. 转换到第一个版本
        resource1 = self._convert_to_version(resource, version1)
        if not resource1:
            return ComparisonResult(
                differences={"error": f"无法转换到版本 {version1}"},
                summary={"error": f"无法转换到版本 {version1}"}
            )
        
        # 2. 转换到第二个版本
        resource2 = self._convert_to_version(resource, version2)
        if not resource2:
            return ComparisonResult(
                differences={"error": f"无法转换到版本 {version2}"},
                summary={"error": f"无法转换到版本 {version2}"}
            )
        
        # 3. 比较差异
        return self.compare_resources(resource1, resource2)
    
    def compare_resource_sets(self, resources1: List[Dict[str, Any]], 
                            resources2: List[Dict[str, Any]]) -> ComparisonResult:
        """
        比较两组资源
        
        Args:
            resources1: 第一组资源
            resources2: 第二组资源
            
        Returns:
            ComparisonResult: 比较结果
        """
        # 1. 构建资源映射
        resources1_map = {self._get_resource_key(r): r for r in resources1}
        resources2_map = {self._get_resource_key(r): r for r in resources2}
        
        # 2. 找出共同资源
        common_keys = set(resources1_map.keys()) & set(resources2_map.keys())
        
        # 3. 比较共同资源
        common_diffs = {}
        for key in common_keys:
            diff = self.compare_resources(resources1_map[key], resources2_map[key])
            common_diffs[key] = diff
        
        # 4. 找出独有资源
        only_in_1 = set(resources1_map.keys()) - set(resources2_map.keys())
        only_in_2 = set(resources2_map.keys()) - set(resources1_map.keys())
        
        # 5. 生成摘要
        summary = {
            "common_resources": len(common_keys),
            "only_in_first": len(only_in_1),
            "only_in_second": len(only_in_2),
            "common_differences": common_diffs
        }
        
        return ComparisonResult(
            differences={
                "common_differences": common_diffs,
                "only_in_first": list(only_in_1),
                "only_in_second": list(only_in_2)
            },
            summary=summary
        )
    
    def _generate_diff_summary(self, diff: Dict[str, Any]) -> Dict[str, Any]:
        """生成差异摘要"""
        summary = {
            "total_changes": 0,
            "added": 0,
            "removed": 0,
            "modified": 0,
            "type_changes": 0,
            "value_changes": 0
        }
        
        # 统计添加的字段
        if "dictionary_item_added" in diff:
            summary["added"] = len(diff["dictionary_item_added"])
            summary["total_changes"] += summary["added"]
        
        # 统计删除的字段
        if "dictionary_item_removed" in diff:
            summary["removed"] = len(diff["dictionary_item_removed"])
            summary["total_changes"] += summary["removed"]
        
        # 统计修改的字段
        if "values_changed" in diff:
            summary["modified"] = len(diff["values_changed"])
            summary["total_changes"] += summary["modified"]
        
        # 统计类型变化的字段
        if "type_changes" in diff:
            summary["type_changes"] = len(diff["type_changes"])
            summary["total_changes"] += summary["type_changes"]
        
        # 统计值变化的字段
        if "values_changed" in diff:
            summary["value_changes"] = len(diff["values_changed"])
        
        return summary
    
    def _generate_visualization(self, resource1: Dict[str, Any], 
                              resource2: Dict[str, Any],
                              diff: Dict[str, Any]) -> Optional[str]:
        """生成可视化比较结果"""
        try:
            # 创建图形
            plt.figure(figsize=(12, 8))
            
            # 添加节点
            self._diff_graph.clear()
            self._add_resource_nodes(resource1, "resource1")
            self._add_resource_nodes(resource2, "resource2")
            
            # 添加边
            self._add_diff_edges(diff)
            
            # 绘制图形
            pos = nx.spring_layout(self._diff_graph)
            nx.draw(self._diff_graph, pos, with_labels=True, node_color='lightblue',
                   node_size=2000, font_size=8, font_weight='bold')
            
            # 保存图形
            plt.savefig("diff_visualization.png")
            plt.close()
            
            return "diff_visualization.png"
            
        except Exception:
            return None
    
    def _add_resource_nodes(self, resource: Dict[str, Any], prefix: str):
        """添加资源节点到图形"""
        for key, value in resource.items():
            node_id = f"{prefix}_{key}"
            self._diff_graph.add_node(node_id, label=f"{key}: {type(value).__name__}")
            
            if isinstance(value, dict):
                self._add_resource_nodes(value, node_id)
            elif isinstance(value, list):
                for i, item in enumerate(value):
                    if isinstance(item, dict):
                        self._add_resource_nodes(item, f"{node_id}_{i}")
    
    def _add_diff_edges(self, diff: Dict[str, Any]):
        """添加差异边到图形"""
        # 添加修改的边
        if "values_changed" in diff:
            for path, change in diff["values_changed"].items():
                old_value = change["old_value"]
                new_value = change["new_value"]
                self._diff_graph.add_edge(
                    f"resource1_{path}",
                    f"resource2_{path}",
                    label=f"Changed: {old_value} -> {new_value}"
                )
        
        # 添加删除的边
        if "dictionary_item_removed" in diff:
            for path in diff["dictionary_item_removed"]:
                self._diff_graph.add_node(
                    f"removed_{path}",
                    label=f"Removed: {path}"
                )
        
        # 添加新增的边
        if "dictionary_item_added" in diff:
            for path in diff["dictionary_item_added"]:
                self._diff_graph.add_node(
                    f"added_{path}",
                    label=f"Added: {path}"
                )
    
    def _get_resource_key(self, resource: Dict[str, Any]) -> str:
        """获取资源的唯一键"""
        return f"{resource.get('kind', 'Unknown')}/{resource.get('metadata', {}).get('name', 'Unknown')}"
    
    def _convert_to_version(self, resource: Dict[str, Any], version: str) -> Optional[Dict[str, Any]]:
        """转换资源到指定版本"""
        try:
            # 创建资源副本
            converted = resource.copy()
            
            # 更新版本
            converted["apiVersion"] = version
            
            return converted
            
        except Exception:
            return None 